home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / gs262 / genconf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-29  |  8.2 KB  |  328 lines

  1. /* Copyright (C) 1993 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* genconf.c */
  20. /* Generate configuration files for Ghostscript */
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <stdlib.h>        /* for calloc */
  24. #include <string.h>
  25.  
  26. /*
  27.  * This program generates a set of configuration files for Ghostscript.
  28.  * Everything it does could be done by a shell program, except that
  29.  * (1) Unix shells are not compatible from one system to another,
  30.  * (2) the DOS shell is not equal to the task,
  31.  * (3) the VMS shell is radically different from all others.
  32.  *
  33.  * Usage:
  34.  *    genconf [@]xxx.dev* [-f gconfigf.h] [-h gconfig.h]
  35.  *      [-l lib.tr] [-o obj.tr] [-u ld.tr] [-w objw.tr]
  36.  */
  37.  
  38. /* This program has to use K&R C, so it will work with old compilers. */
  39. #ifndef AMIGA
  40. #undef const
  41. #define const /* */
  42. #define P1(a1) /* */
  43. #define P2(a1,a2) /* */
  44. #define P3(a1,a2,a3) /* */
  45. #else
  46. #define P1(t1) t1
  47. #define P2(t1,t2) t1,t2
  48. #define P3(t1,t2,t3) t1,t2,t3
  49. #endif
  50. /* Unfortunately, we have to hack up the function definitions by hand. */
  51.  
  52. /* Structures for accumulating information */
  53. typedef struct string_list_s {
  54.     int max_count, count;
  55.     char **strings;
  56. } string_list;
  57. typedef struct config_s {
  58.     string_list resources;
  59.     string_list devs;
  60.     string_list fonts;
  61.     string_list libs;
  62.     string_list objs;
  63. } config;
  64. static const config init_config = {
  65.     { 200 }, { 100 }, { 200 }, { 100 }, { 200 }
  66. };
  67.  
  68. /* Forward definitions */
  69. int alloc_list(P1(string_list *));
  70. int read_dev(P2(config *, const char *));
  71. int read_token(P3(char *, int, FILE *));
  72. int add_entry(P3(config *, char *, const char *));
  73. void sort_uniq(P1(string_list *));
  74. void write_list(P3(FILE *, const string_list *, const char *));
  75.  
  76. #ifndef AMIGA
  77. main(argc, argv) int argc; char *argv[];
  78. #else
  79. main(int argc, char *argv[])
  80. #endif
  81. {    config conf;
  82.     int i;
  83.  
  84.     /* Allocate string lists. */
  85.     conf = init_config;
  86.     alloc_list(&conf.resources);
  87.     alloc_list(&conf.devs);
  88.     alloc_list(&conf.fonts);
  89.     alloc_list(&conf.libs);
  90.     alloc_list(&conf.objs);
  91.  
  92.     /* Process command line arguments. */
  93.     for ( i = 1; i < argc; i++ )
  94.     {    const char *arg = argv[i];
  95.         FILE *out;
  96.         if ( *arg != '-' )
  97.         {    read_dev(&conf, arg);
  98.             continue;
  99.         }
  100.         if ( i == argc - 1 )
  101.         {    fprintf(stderr, "Missing file name after %s.\n",
  102.                 arg);
  103.             exit(1);
  104.         }
  105.         out = fopen(argv[++i], "w");
  106.         if ( out == 0 )
  107.         {    fprintf(stderr, "Can't open %s for output.\n",
  108.                 argv[i]);
  109.             exit(1);
  110.         }
  111.         switch ( arg[1] )
  112.         {
  113.         case 'f':
  114.             fputs("/* This file was generated automatically by Ghostscript (genconf.c). */\n", out);
  115.             write_list(out, &conf.fonts,
  116.                    "font_(\"0.font_%s\",gsf_%s,zf_%s)\n");
  117.             break;
  118.         case 'h':
  119.             fputs("/* This file was generated automatically by Ghostscript (genconf.c). */\n", out);
  120.             fputs("#include \"gsconfig.h\"\n", out);
  121.             write_list(out, &conf.devs, "device__(gs_%s_device)\n");
  122.             sort_uniq(&conf.resources);
  123.             write_list(out, &conf.resources, "%s\n");
  124.             break;
  125.         case 'l':
  126.             write_list(out, &conf.libs, "%s+\n");
  127.             break;
  128.         case 'o':
  129.             sort_uniq(&conf.objs);
  130.             write_list(out, &conf.objs, "%s+\n");
  131.             break;
  132.         case 'u':
  133.             sort_uniq(&conf.objs);
  134. #ifndef __SASC
  135.             write_list(out, &conf.objs, "%s \\\n");
  136.             write_list(out, &conf.libs, "-l%s \\\n");
  137. #else
  138.             write_list(out, &conf.objs, "%s \n");
  139.             write_list(out, &conf.libs, "%s \n");
  140. #endif
  141.             break;
  142.         case 'w':
  143.             sort_uniq(&conf.objs);
  144.             write_list(out, &conf.objs, "FILE %s\n");
  145.             break;
  146.         default:
  147.             fclose(out);
  148.             fprintf(stderr, "Unknown switch %s.\n", arg);
  149.             exit(1);
  150.         }
  151.         fclose(out);
  152.     }
  153.  
  154.     exit(0);
  155. }
  156.  
  157. /* Allocate and initialize a string list. */
  158. int
  159. #ifndef AMIGA
  160. alloc_list(list) string_list *list;
  161. #else
  162. alloc_list(string_list *list)
  163. #endif
  164. {    list->count = 0;
  165.     list->strings =
  166.         (char **)calloc(list->max_count, sizeof(char *));
  167.     return 0;
  168. }
  169.  
  170. /* Read and parse a .dev file. */
  171. int
  172. #ifndef AMIGA
  173. read_dev(pconf, arg) config *pconf; const char *arg;
  174. #else
  175. read_dev(config *pconf, const char *arg)
  176. #endif
  177. {    FILE *in;
  178. #define max_token 32
  179.     char token[max_token];
  180.     int len;
  181.     if ( arg[0] == '@' )
  182.     {    in = fopen(arg + 1, "r");
  183.         if ( in == 0 )
  184.         {    fprintf(stderr, "Can't read %s.\n", arg + 1);
  185.             exit(1);
  186.         }
  187.         while ( (len = read_token(token, max_token, in)) > 0 )
  188.             read_dev(pconf, token);
  189.     }
  190.     else
  191.     {    char category[max_token];
  192.         in = fopen(arg, "r");
  193.         if ( in == 0 )
  194.         {    fprintf(stderr, "Can't read %s.\n", arg);
  195.             exit(1);
  196.         }
  197.         strcpy(category, "obj");
  198.         while ( (len = read_token(token, max_token, in)) > 0 )
  199.             add_entry(pconf, category, token);
  200.     }
  201. #undef max_token
  202.     fclose(in);
  203.     if ( len < 0 )
  204.     {    fprintf(stderr, "Token too long: %s.\n", token);
  205.         exit(1);
  206.     }
  207.     return 0;
  208. }
  209.  
  210. /* Read a token from a file. */
  211. int
  212. #ifndef AMIGA
  213. read_token(token, max_len, in) char *token; int max_len; FILE *in;
  214. #else
  215. read_token(char *token, int max_len, FILE *in)
  216. #endif
  217. {    int len = 0;
  218.     for ( ; ; ) 
  219.     {    char ch = fgetc(in);
  220.         token[len] = 0;
  221.         if ( feof(in) )
  222.             return len;
  223.         if ( isspace(ch) )
  224.         {    if ( len > 0 )
  225.                 return len;
  226.             continue;
  227.         }
  228.         if ( len == max_len )
  229.             return -1;    /* token too long */
  230.         token[len++] = ch;
  231.     }
  232. }
  233.  
  234. /* Add an entry to a configuration. */
  235. int
  236. #ifndef AMIGA
  237. add_entry(pconf, category, item) config *pconf; char *category; const char *item;
  238. #else
  239. add_entry(config *pconf, char *category, const char *item)
  240. #endif
  241. {    if ( item[0] == '-' )        /* set category */
  242.         strcpy(category, item + 1);
  243.     else                /* add to current category */
  244.     {    char str[80];
  245.         const char *pat = "%s";
  246.         char *rstr;
  247.         string_list *list = &pconf->resources;
  248.         /* Handle a few resources specially: */
  249.         if ( !strcmp(category, "dev") )
  250.             list = &pconf->devs;
  251.         else if ( !strcmp(category, "font") )
  252.             list = &pconf->fonts;
  253.         else if ( !strcmp(category, "include") )
  254.         {    strcpy(str, item);
  255.             strcat(str, ".dev");
  256.             read_dev(pconf, str);
  257.             return 0;
  258.         }
  259.         else if ( !strcmp(category, "lib") )
  260.             list = &pconf->libs;
  261.         else if ( !strcmp(category, "obj") )
  262.             list = &pconf->objs;
  263.         /* Now handle all other resources. */
  264.         else if ( !strcmp(category, "fdev") )
  265.             pat = "file_device__(gs_fdev_%s)";
  266.         else if ( !strcmp(category, "oper") )
  267.             pat = "oper__(%s_op_defs)";
  268.         else if ( !strcmp(category, "oper2") )
  269.             pat = "oper2__(%s_op_defs)";
  270.         else if ( !strcmp(category, "ps") )
  271.             pat = "psfile__(\"%s.ps\")";
  272.         else
  273.         {    fprintf(stderr, "Unknown category %s.\n", category);
  274.             exit(1);
  275.         }
  276.         sprintf(str, pat, item);
  277.         rstr = malloc(strlen(str) + 1);
  278.         strcpy(rstr, str);
  279.         list->strings[list->count++] = rstr;
  280.     }
  281.     return 0;
  282. }
  283.  
  284. /* Sort and uniq an array of strings. */
  285. int
  286. #ifndef AMIGA
  287. strcmp_ptr(ps1, ps2) const void *ps1; const void *ps2;
  288. #else
  289. strcmp_ptr(const void *ps1, const void *ps2)
  290. #endif
  291. {    return strcmp(*(const char **)ps1, *(const char **)ps2);
  292. }
  293. void
  294. #ifndef AMIGA
  295. sort_uniq(list) string_list *list;
  296. #else
  297. sort_uniq(string_list *list)
  298. #endif
  299. {    char **strlist = list->strings;
  300.     int count = list->count;
  301.     char **from;
  302.     char **to;
  303.     int i;
  304.     if ( count == 0 )
  305.         return;
  306.     qsort((char *)strlist, count, sizeof(char *), strcmp_ptr);
  307.     for ( from = to = strlist + 1, i = 1; i < count; from++, i++ )
  308.       if ( strcmp(*from, to[-1]) )
  309.         *to++ = *from;
  310.     list->count = to - strlist;
  311. }
  312.  
  313. /* Write a list of strings using a template. */
  314. void
  315. #ifndef AMIGA
  316. write_list(out, list, template) FILE *out; const string_list *list; const char *template;
  317. #else
  318. write_list(FILE *out, const string_list *list, const char *template)
  319. #endif
  320. {    int i;
  321.     for ( i = 0; i < list->count; i++ )
  322.     {    const char *str = list->strings[i];
  323.         /* The repetition of str is a hack to make the */
  324.         /* fonts template work. */
  325.         fprintf(out, template, str, str, str);
  326.     }
  327. }
  328.